﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using Crawler_v1.spider.entity;
using Crawler_v1.spider.exception;

namespace Crawler_v1.spider
{

    class ThreadSpider
    {
        private int maxCount = 2;//线程数量

        private int runningCount = 0;//当前线程数量
        private volatile Boolean isRunning = false;//运行开关

        private Schedule schedule;//文章url列表提前
        private ContentProcessor contentProcessor;//html解析
        private ISpiderListener spiderListener;//和窗口交互
        private SqlitePipeLine sqlitePipeLine;//保存数据库

        internal SqlitePipeLine SqlitePipeLine
        {
            get { return sqlitePipeLine; }
            set { 
                sqlitePipeLine = value;
                sqlitePipeLine.onAttachSpider(this);
            }
        }

        internal ISpiderListener SpiderListener
        {
            get { return spiderListener; }
            set { spiderListener = value;}
        }

        internal ContentProcessor ContentProcessor
        {
            get { return contentProcessor; }
            set { contentProcessor = value; }
        }

        internal Schedule MySchedule
        {
            get
            {
                return schedule;
            }
            set
            {
                schedule = value;
                schedule.onAttachSpider(this);
            }
        }


        public ThreadSpider(Schedule schedule,SqlitePipeLine sqlitePipeLine)
        {
            MySchedule = schedule;
            SqlitePipeLine = sqlitePipeLine;
            contentProcessor = new ContentProcessor();
            
            //SqlitePipeLine.onAttachSpider(this);
            //MySchedule.onAttachSpider(this);
        }


        public bool isStarted()
        {
            return isRunning;
        }

        public void start()
        {
            isRunning = true;
            runningCount = 0;
            for (int count = 0; count < maxCount; count++)
            {
                create(count);
            }
        }

        public void stop()
        {
            isRunning = false;
        }

        public void create(int count)
        {

            new Thread((index) =>
            {
                int threadIndex = Convert.ToInt32(index);

                Interlocked.Increment(ref runningCount);
                Console.WriteLine("线程【" + threadIndex + "】开始！");

                while (isRunning)
                {

                    Page page;
                    lock (schedule.locker)
                    {
                        page = schedule.getOneUrl();
                    }

                    if (page != null)
                    {
                        try
                        {
                            //解析
                            contentProcessor.parse(page);
                            //保存到数据库
                            sqlitePipeLine.save(page);

                            if (spiderListener != null)
                            {
                                spiderListener.onFinishOne(page);
                            }


                        }
                        catch (Exception ex)
                        {
                            spiderListener.onError(ex);
                            Console.WriteLine("TempIsZeroException: {0}", ex.Message);

                        }
                        

                    }
                    else
                    {

                        //schedule没有url了，退出
                        break;

                    }

                    Thread.Sleep(100);
                }


                lock (schedule.locker)
                {
                    int count1 = getRunningCount();

                    if (count1 == 1)//最后一个退出的线程
                    {

                        spiderListener.onFinishAll();
                        isRunning = false;
                    }

                    Interlocked.Decrement(ref runningCount);
                }


                Console.WriteLine("线程【" + threadIndex + "】结束！");

            }).Start(count);

        }

        public int getRunningCount()
        {
            return Thread.VolatileRead(ref runningCount);
        }

    }
}
